Skip to content

[fix](storage) align pruned complex column types with sub-column iterators on merge/agg read paths#65396

Open
csun5285 wants to merge 1 commit into
apache:masterfrom
csun5285:fix-topn-pruned-struct-merge
Open

[fix](storage) align pruned complex column types with sub-column iterators on merge/agg read paths#65396
csun5285 wants to merge 1 commit into
apache:masterfrom
csun5285:fix-topn-pruned-struct-merge

Conversation

@csun5285

@csun5285 csun5285 commented Jul 8, 2026

Copy link
Copy Markdown
Contributor
  1. VMergeIteratorContext::block_reset built per-segment merge blocks from the storage Schema (full type). A topn ordered read over a rowset with multiple OVERLAPPING segments then decoded pruned children into the wrong dst columns

  2. BlockReader::_init_agg_state built the reader_replace argument type from the raw TabletColumn (full type) while the stored block uses the pruned type. On AGG tables any pruned read that goes through the aggregate merge path (>= 2 data rowsets, no special session vars needed) failed with "Aggregate function reader_replace argument 0 type check failed: ColumnStruct has 2 elements, but DataTypeStruct has 3 elements".

What problem does this PR solve?

Issue Number: close #xxx

Related PR: #xxx

Problem Summary:

Release note

None

Check List (For Author)

  • Test

    • Regression test
    • Unit Test
    • Manual test (add detailed scripts or steps below)
    • No need to test or manual test. Explain why:
      • This is a refactor/code format and no logic has been changed.
      • Previous test can cover this change.
      • No code files have been changed.
      • Other reason
  • Behavior changed:

    • No.
    • Yes.
  • Does this need documentation?

    • No.
    • Yes.

Check List (For Reviewer who merge this PR)

  • Confirm the release note
  • Confirm test cases
  • Confirm document
  • Add branch pick label

@hello-stephen

Copy link
Copy Markdown
Contributor

Thank you for your contribution to Apache Doris.
Don't know what should be done next? See How to process your PR.

Please clearly describe your PR:

  1. What problem was fixed (it's best to include specific error reporting information). How it was fixed.
  2. Which behaviors were modified. What was the previous behavior, what is it now, why was it modified, and what possible impacts might there be.
  3. What features were added. Why was this function added?
  4. Which code was refactored and why was this part of the code refactored?
  5. Which functions were optimized and what is the difference before and after the optimization?

@csun5285

csun5285 commented Jul 8, 2026

Copy link
Copy Markdown
Contributor Author

run buildall

@csun5285

csun5285 commented Jul 8, 2026

Copy link
Copy Markdown
Contributor Author

/review

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review result: requesting changes for one regression-test oracle issue.

Critical checkpoint conclusions:

  • Goal/correctness: the C++ change threads pruned complex-column data types through the query scan schema, merge iterator, and aggregate reader paths; I did not find an additional functional bug in those inspected paths.
  • Scope: the implementation is focused on query-pruned type propagation plus one regression test.
  • Concurrency/lifecycle: no new thread, lock, static initialization, or ownership lifecycle risk was introduced by the changed code.
  • Compatibility/persistence/config: no new persisted format, FE-BE protocol field, or config item was added; the pruned-column type map is query-local and shawdow_copy_without_columns clears it.
  • Parallel paths: TopN merge-reader, aggregate reader, ordinary materialization/rowid fetch, and compaction/vertical-reader paths were checked. Compaction/vertical paths do not use query-pruned maps.
  • Tests: the regression targets the right failure family, but its layout self-check does not prove the rowset has more than one segment, which is required to select VMergeIterator.
  • Validation: static review only. This checkout is shallow/missing the base SHA, .worktree_initialized, thirdparty/installed, and thirdparty/installed/bin/protoc, so I did not build or run regression tests.
  • User focus: no additional user-provided review focus was present.

Subagent conclusions: optimizer-rewrite reported no valuable findings. tests-session-config proposed TSC-001, accepted as MAIN-001 and submitted inline. Convergence round 1 ended with both live subagents replying NO_NEW_VALUABLE_FINDINGS for the same final ledger/comment set.

@hello-stephen

Copy link
Copy Markdown
Contributor

BE UT Coverage Report

Increment line coverage 45.10% (23/51) 🎉

Increment coverage report
Complete coverage report

Category Coverage
Function Coverage 56.54% (23211/41055)
Line Coverage 40.10% (225250/561730)
Region Coverage 36.05% (177908/493515)
Branch Coverage 37.11% (79085/213135)

@hello-stephen

Copy link
Copy Markdown
Contributor

BE Regression && UT Coverage Report

Increment line coverage 78.43% (40/51) 🎉

Increment coverage report
Complete coverage report

Category Coverage
Function Coverage 73.09% (29290/40075)
Line Coverage 56.69% (316604/558513)
Region Coverage 53.20% (263672/495601)
Branch Coverage 54.25% (115749/213370)

@csun5285 csun5285 force-pushed the fix-topn-pruned-struct-merge branch 4 times, most recently from 6141226 to 7cad469 Compare July 9, 2026 07:46
@csun5285 csun5285 requested a review from luwei16 as a code owner July 9, 2026 07:46
@csun5285 csun5285 force-pushed the fix-topn-pruned-struct-merge branch 4 times, most recently from d69fffb to ac507fb Compare July 9, 2026 08:15
@csun5285

csun5285 commented Jul 9, 2026

Copy link
Copy Markdown
Contributor Author

run buildall

@csun5285

csun5285 commented Jul 9, 2026

Copy link
Copy Markdown
Contributor Author

/review

…ators on merge/agg read paths

When a query prunes nested sub-columns of a complex column (EXPLAIN shows
"pruned type"), the scan's struct sub-column iterators are filtered down to
the pruned subset (set_access_paths + remove_pruned_sub_iterators), while the
FE-pruned data type is recorded only in TabletSchema::_pruned_columns_data_type
and honored only by TabletSchema::create_block*. Read paths that materialize
column shapes from other sources still used the FULL storage type, so the
positional pairing in StructFileColumnIterator::next_batch worked on two
different ordinal spaces:

1. VMergeIteratorContext::block_reset built per-segment merge blocks from the
   storage Schema (full type). A topn ordered read over a rowset with multiple
   OVERLAPPING segments then decoded pruned children into the wrong dst
   columns:
   - "[E-3110] Method insert_many_dict_data is not supported for TINYINT"
     (dict-encoded text child decoded into a tinyint child)
   - "... is not supported for INT" (single-child pruning variant)
   - BE SIGSEGV when the shifted child types happen to match and the loop
     runs past the pruned iterator vector (same family as DORIS-26595)
   This is the root cause of DORIS-26889: the CI's s3 insert naturally
   produces overlapping multi-segment rowsets, while single-segment local
   loads never take the merge path. On master the default plan usually
   shields this path via TopN lazy materialization (apache#63736 + apache#64242), but
   e.g. raising topn_opt_limit_threshold, disabling
   topn_lazy_materialization_threshold, or light_schema_change=false tables
   expose it; branch-4.1 hits it by default.

2. BlockReader::_init_agg_state built the reader_replace argument type from
   the raw TabletColumn (full type) while the stored block uses the pruned
   type. On AGG tables any pruned read that goes through the aggregate merge
   path (>= 2 data rowsets, no special session vars needed) failed with
   "Aggregate function reader_replace argument 0 type check failed:
   ColumnStruct has 2 elements, but DataTypeStruct has 3 elements".

Fix: make the shape-materializing read paths use the same FE-pruned type as
the sub-column iterators, so dst blocks and iterators stay in one ordinal
space by construction.
- VMergeIteratorContext::init reads the FE-pruned complex types from
  StorageReadOptions::tablet_schema (TabletSchema::pruned_columns_data_type(),
  already set on the query read path), and block_reset then builds each merge
  block with the pruned type for pruned columns and the full storage type for
  the rest, so the block's struct children align with the pruned sub-column
  iterators. No new plumbing through the merge iterator or the storage Schema.
- TabletColumn::get_aggregate_function now takes the column's actual data type
  explicitly. BlockReader::_init_agg_state passes the stored block's column
  type (already the pruned type for pruned complex columns), while the
  load/compaction/schema-change paths pass the full column type.

The new regression case constructs an OVERLAPPING multi-segment rowset
deterministically (MemTable.need_flush debug point + NULL keys in every
batch, segment count kept below the segcompaction threshold), self-checks the
layout via tablet meta, and covers all variants: the dict-error and
SIGSEGV topn shapes on the inline path, the AGG default-session shape across
two rowsets, and the VMaterializeNode default path as a guard. All variants
fail before this fix and pass after it.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@csun5285 csun5285 force-pushed the fix-topn-pruned-struct-merge branch from ac507fb to fb7a8df Compare July 9, 2026 08:22
@csun5285

csun5285 commented Jul 9, 2026

Copy link
Copy Markdown
Contributor Author

run buildall

@csun5285

csun5285 commented Jul 9, 2026

Copy link
Copy Markdown
Contributor Author

/review

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review result: no new distinct inline comments in this pass. The existing line-100 thread remains the only actionable issue I found, and I did not duplicate it.

Critical checkpoint conclusions:

  • Goal/correctness: the PR aligns FE-pruned complex-column types with the merge block and aggregate-reader function paths. I checked the scan setup, TabletReader, BetaRowsetReader, VMergeIteratorContext, BlockReader::_init_agg_state, rowid-fetch materialization, and compaction/schema-change call sites; I found no additional correctness issue.
  • Scope: the implementation is focused on pruned type propagation plus one regression test.
  • Concurrency/lifecycle: no new thread, lock, static initialization, or storage lifetime risk was introduced; the pruned type map is query-local and read through the tablet schema held by the reader path.
  • Compatibility/config/persistence: no new persisted format, FE-BE protocol field, or config item was added.
  • Parallel paths: query TopN merge and AGG reader paths use the pruned block/type shape; load, schema-change, and vertical compaction callers continue to pass full storage types.
  • Tests: the regression covers default materialization, forced inline TopN, and AGG merge reads. The remaining test oracle gap is already covered by existing thread discussion_r3544580724: line 100 still checks only segments_overlap_pb and should also assert num_segments > 1.
  • Validation: static review only. This checkout is shallow and lacks .worktree_initialized, thirdparty/installed, and thirdparty/installed/bin/protoc, so I did not build or run regression tests. I refreshed the live PR head (fb7a8dfb66da7c750db6101d2dd6c2bb38331e90); it differs from the local checkout only by comment wording in two C++ files.
  • User focus: no additional user-provided review focus was present.

Subagent conclusions: both required subagents reported only the duplicate of existing thread discussion_r3544580724. The main merge recorded that as MAIN-DUP-001 with no new proposed inline comments. Convergence round 2, after the live-head refresh, ended with both live subagents replying NO_NEW_VALUABLE_FINDINGS for the same ledger/comment set.

@github-actions

github-actions Bot commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

Codex automated review failed and did not complete.

Error: Codex completed, but no new pull request review was submitted for the current head SHA.
Workflow run: https://github.com/apache/doris/actions/runs/29004201867

Please inspect the workflow logs and rerun the review after the underlying issue is resolved.

@HappenLee HappenLee left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@hello-stephen

Copy link
Copy Markdown
Contributor

BE UT Coverage Report

Increment line coverage 43.48% (10/23) 🎉

Increment coverage report
Complete coverage report

Category Coverage
Function Coverage 56.63% (23253/41060)
Line Coverage 40.18% (225711/561785)
Region Coverage 36.08% (178134/493754)
Branch Coverage 37.15% (79189/213135)

@github-actions github-actions Bot added the approved Indicates a PR has been approved by one committer. label Jul 9, 2026
@github-actions

github-actions Bot commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

PR approved by at least one committer and no changes requested.

@hello-stephen

Copy link
Copy Markdown
Contributor
TPC-H: Total hot run time: 29975 ms
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/tpch-tools
Tpch sf100 test result on commit fb7a8dfb66da7c750db6101d2dd6c2bb38331e90, data reload: false

------ Round 1 ----------------------------------
============================================
q1	17608	4254	4172	4172
q2	2064	345	216	216
q3	10251	1459	870	870
q4	4686	479	342	342
q5	7532	876	588	588
q6	189	173	140	140
q7	782	879	628	628
q8	9366	1653	1559	1559
q9	5724	4413	4428	4413
q10	6767	1796	1520	1520
q11	502	347	328	328
q12	736	558	439	439
q13	18074	3458	2811	2811
q14	269	267	236	236
q15	q16	800	785	718	718
q17	1044	978	957	957
q18	6946	5730	5641	5641
q19	1194	1259	1072	1072
q20	726	646	566	566
q21	5521	2579	2456	2456
q22	434	362	303	303
Total cold run time: 101215 ms
Total hot run time: 29975 ms

----- Round 2, with runtime_filter_mode=off -----
============================================
q1	4423	4500	4432	4432
q2	305	325	216	216
q3	4596	4985	4412	4412
q4	2134	2237	1381	1381
q5	4507	4373	4405	4373
q6	237	175	129	129
q7	1739	2842	1707	1707
q8	2597	2264	2244	2244
q9	8004	7996	7764	7764
q10	4774	4747	4298	4298
q11	609	415	413	413
q12	759	768	630	630
q13	3112	3390	2796	2796
q14	287	288	257	257
q15	q16	699	723	613	613
q17	1311	1308	1280	1280
q18	7465	7109	7043	7043
q19	1089	1076	1071	1071
q20	2215	2223	1980	1980
q21	5327	4713	4678	4678
q22	535	479	399	399
Total cold run time: 56724 ms
Total hot run time: 52116 ms

@hello-stephen

Copy link
Copy Markdown
Contributor
TPC-DS: Total hot run time: 181241 ms
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/tpcds-tools
TPC-DS sf100 test result on commit fb7a8dfb66da7c750db6101d2dd6c2bb38331e90, data reload: false

query5	4318	630	493	493
query6	460	233	216	216
query7	4861	611	338	338
query8	349	194	172	172
query9	8786	4104	4151	4104
query10	473	350	297	297
query11	5823	2365	2155	2155
query12	173	106	103	103
query13	1269	631	442	442
query14	6281	5342	5022	5022
query14_1	4332	4368	4318	4318
query15	219	210	186	186
query16	1034	484	499	484
query17	943	753	601	601
query18	2459	471	337	337
query19	208	185	149	149
query20	109	106	108	106
query21	227	154	133	133
query22	13666	13750	13328	13328
query23	17417	16620	16793	16620
query23_1	16311	16348	16276	16276
query24	7498	1838	1296	1296
query24_1	1297	1299	1301	1299
query25	539	443	357	357
query26	1333	351	223	223
query27	2567	591	372	372
query28	4453	2066	2057	2057
query29	1061	610	489	489
query30	340	259	222	222
query31	1128	1101	1028	1028
query32	104	61	64	61
query33	528	311	279	279
query34	1172	1121	657	657
query35	797	770	666	666
query36	1372	1352	1184	1184
query37	164	103	94	94
query38	1875	1705	1650	1650
query39	925	932	910	910
query39_1	890	872	874	872
query40	242	163	143	143
query41	66	62	61	61
query42	90	86	92	86
query43	319	325	296	296
query44	1507	780	777	777
query45	195	188	178	178
query46	1106	1207	726	726
query47	2426	2366	2204	2204
query48	410	415	308	308
query49	590	434	316	316
query50	1026	436	333	333
query51	10627	10921	10773	10773
query52	84	86	75	75
query53	270	281	208	208
query54	285	257	217	217
query55	75	71	65	65
query56	284	284	289	284
query57	1407	1426	1298	1298
query58	283	275	264	264
query59	1618	1675	1461	1461
query60	295	265	260	260
query61	159	149	150	149
query62	688	645	577	577
query63	250	199	204	199
query64	2867	1014	873	873
query65	4889	4806	4795	4795
query66	1824	504	386	386
query67	29588	29592	29356	29356
query68	3074	1579	1052	1052
query69	429	319	274	274
query70	1075	973	931	931
query71	344	341	300	300
query72	3067	2790	2576	2576
query73	850	789	423	423
query74	5261	4970	4787	4787
query75	2638	2606	2250	2250
query76	2338	1245	818	818
query77	369	397	304	304
query78	12349	12408	11791	11791
query79	1405	1164	813	813
query80	777	589	483	483
query81	487	331	284	284
query82	572	157	129	129
query83	397	329	312	312
query84	324	166	142	142
query85	1064	592	509	509
query86	412	295	297	295
query87	1836	1819	1756	1756
query88	3746	2839	2819	2819
query89	450	411	350	350
query90	1787	200	203	200
query91	200	191	161	161
query92	65	63	57	57
query93	1537	1527	952	952
query94	621	378	308	308
query95	784	571	476	476
query96	1031	791	375	375
query97	2695	2708	2563	2563
query98	212	209	209	209
query99	1162	1184	1019	1019
Total cold run time: 264882 ms
Total hot run time: 181241 ms

@hello-stephen

Copy link
Copy Markdown
Contributor
ClickBench: Total hot run time: 25.11 s
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/clickbench-tools
ClickBench test result on commit fb7a8dfb66da7c750db6101d2dd6c2bb38331e90, data reload: false

query1	0.00	0.00	0.00
query2	0.10	0.05	0.05
query3	0.25	0.14	0.12
query4	1.60	0.14	0.14
query5	0.25	0.27	0.22
query6	1.24	1.11	1.09
query7	0.05	0.01	0.01
query8	0.06	0.04	0.03
query9	0.38	0.32	0.31
query10	0.58	0.55	0.58
query11	0.19	0.15	0.14
query12	0.19	0.14	0.13
query13	0.47	0.48	0.47
query14	1.00	1.01	1.01
query15	0.61	0.60	0.60
query16	0.32	0.32	0.33
query17	1.14	1.11	1.12
query18	0.23	0.21	0.21
query19	2.03	1.98	1.95
query20	0.02	0.01	0.02
query21	15.46	0.23	0.14
query22	4.75	0.06	0.05
query23	16.13	0.31	0.13
query24	2.89	0.44	0.32
query25	0.11	0.07	0.04
query26	0.75	0.20	0.15
query27	0.03	0.04	0.03
query28	3.53	0.87	0.51
query29	12.56	4.05	3.25
query30	0.27	0.15	0.16
query31	2.78	0.58	0.32
query32	3.24	0.58	0.50
query33	3.18	3.34	3.20
query34	15.68	4.27	3.53
query35	3.50	3.55	3.52
query36	0.56	0.44	0.41
query37	0.09	0.06	0.06
query38	0.05	0.04	0.04
query39	0.04	0.03	0.03
query40	0.18	0.18	0.16
query41	0.09	0.04	0.03
query42	0.04	0.03	0.03
query43	0.04	0.04	0.04
Total cold run time: 96.66 s
Total hot run time: 25.11 s

@hello-stephen

Copy link
Copy Markdown
Contributor

BE Regression && UT Coverage Report

Increment line coverage 56.52% (13/23) 🎉

Increment coverage report
Complete coverage report

Category Coverage
Function Coverage 72.97% (29240/40074)
Line Coverage 56.60% (316103/558528)
Region Coverage 53.07% (263108/495802)
Branch Coverage 54.10% (115431/213354)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

approved Indicates a PR has been approved by one committer.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants